﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Fetion.Core
{
   /// <summary>
   /// 基于结束符的分析器
   /// 会在发送消息前写下消息类型名称长度(int),消息类型名称(string)和在消息尾部写结束数据(指定的byte[])
   /// 可以通过重写MessageWrite和MessageRead来自定义自己需要的规则.
   /// </summary>
    public abstract  class EofDataOfPackage : Package
    {
        /// <summary>
        /// 构建分析器
        /// </summary>
        public EofDataOfPackage()
        {
            
            
           
        }
        protected abstract IMessage ReadMessageByType(BufferReader reader, out object typetag);
        protected abstract void WriteMessageType(IMessage msg, BufferWriter writer);
        /// <summary>
        /// 根据名称获取消息对象
        /// </summary>
        /// <param name="name">名称</param>
        /// <returns>IMessage</returns>
        protected abstract IMessage GetMessage(string name);
        /// <summary>
        /// 获取分隔符内容,源生类重写
        /// </summary>
        protected abstract byte[] EofData
        {
            get;
        }
        public override byte[] GetMessageData(IMessage e)
        {
           
            BufferWriter bw = new BufferWriter(Coding);
            bw.EnabledVariant = EnabledVariant;
            WriteMessageType(e, bw);
            e.Save(bw);
            bw.Write(EofData, 0, EofData.Length);
            BufferReader reader = new BufferReader(Coding, bw);
            return reader.ToBytes();
        }
        /// <summary>
        /// 获取消息方法
        /// </summary>
        /// <param name="reader">流读取对象</param>
        /// <returns>IMessage</returns>
        public void MessageRead(BufferReader reader)
        {
            string name = reader.ReadString();
            IMessage msg = GetMessage(name);
            if(msg ==null)
                throw NetTcpException.TypeNotFound(name);
            try
            {
                msg.Load(reader);
             }
            catch (Exception e)
            {
                NetTcpException err = NetTcpException.ObjectLoadError(name,e);
              
                throw err;
            }

            OnReceive(msg);
        }
        BufferWriter Writer;
        private int tmpEofdata = 0;
        private bool mNullData = true;
        /// <summary>
        /// 数据导入
        /// </summary>
        /// <param name="data">byte[]数组</param>
        /// <param name="start">开始位置</param>
        /// <param name="count">导入长度</param>
        public override void Import(byte[] data, int start, int count,EventHandler<ClientAsyncCompletedEventArgs<object>> handle)
        {
            int endindex = start + count;
            int index;
            while (count>0)
            {
                if (mNullData)
                {
                    Writer = new BufferWriter(Coding);
                    Writer.EnabledVariant = EnabledVariant;
                    mNullData = false;
                }
                if (tmpEofdata ==0)
                {
                    index = ByteIndexOf(data, EofData, start, count);
                    if (index == -1)
                    {
                        Writer.Write(data, start, count);
                        int matchindex = 0;
                        bool match = false;
                        for (int i = endindex - (EofData.Length - 1); i < endindex;i++ )
                        {
                            match = true;
                            for (int j = 0; j < EofData.Length; j++)
                            {
                                if (i + j >= endindex)
                                    break;
                                if (data[i + j] != EofData[j])
                                {
                                    match = false;
                                    continue;
                                }
                            }
                            if (match)
                            {
                                matchindex = i;
                                break;
                            }
                        }
                        if (matchindex != 0)
                        {
                            tmpEofdata=endindex-matchindex;
                           
                           
                        }
                        break;
                    }
                    else
                    {

                        Writer.Write(data, start, count);
                        start = index + 1;
                        count = endindex - start;

                        BufferReader reader = new BufferReader(Coding, Writer);
                        reader.EnabledVariant = EnabledVariant;
                        MessageRead(reader);
                        tmpEofdata = 0;
                        mNullData = true;
                    }
                }
                else
                {
                    bool match = true;
                    int length = EofData.Length - tmpEofdata;
                    for (int i = tmpEofdata; i < EofData.Length; i++)
                    {
                        if (data[i - tmpEofdata] != EofData[i])
                        {
                            match = false;
                        }
                    }
                    if (match)
                    {
                        Writer.Write(data, start, length);
                        start = start + length;
                        count = endindex - start;
                        BufferReader reader = new BufferReader(Coding, Writer);
                        reader.EnabledVariant = EnabledVariant;
                        MessageRead(reader);
                        mNullData = true;
                    }
                    tmpEofdata = 0;

                }               
            }
        }
       
    }
}
